
#include "ut.h"

#include <ql/ql.h>

#include <assert.h>
#include <string.h>

static void
err_callback(struct QlAllocContext * c, QlErr err)
{
    fprintf(stderr, "alloc context 0x%p error: %d\n", c, err);
    assert(!"AllocContext's operation failed");
}

/*
 * test identifiers allocation
 */

static void id_alloc_tst()
{
    struct QlId * id1;
    struct QlId * id2;
    struct QlId * id3;

    struct QlAllocContext * c;
    QL_UT_BEGIN("id alloc");

    c = ql_create_alloc_context();
    QL_UT_VERIFY_CRITICAL(c != NULL);

    id1 = ql_alloc_id(c, "flow");
    id2 = ql_alloc_id(c, "flow");
    id3 = ql_alloc_id(c, "String");

    QL_UT_VERIFY((id1 == id2) && (id2 != id3));
    QL_UT_VERIFY(0 == strcmp("flow", ql_get_id_str(id2)));
    QL_UT_VERIFY(0 == strcmp("String", ql_get_id_str(id3)));

    id1 = ql_alloc_id(c, "a");
    QL_UT_VERIFY(0 == strcmp("a", ql_get_id_str(id1)));
    QL_UT_VERIFY(0 == strcmp("flow", ql_get_id_str(id2)));
    QL_UT_VERIFY(0 == strcmp("String", ql_get_id_str(id3)));

    ql_free_alloc_context(c);
    QL_UT_END();
}

/*
 * test cdr allocation
 */

static void cdr_alloc_tst()
{
    struct QlAllocContext * c;
    QL_UT_BEGIN("cdr alloc");
    
    c = ql_create_alloc_context();
    QL_UT_VERIFY_CRITICAL(c != NULL);

    ql_free_alloc_context(c);
    QL_UT_END();
}

static void alloctst1()
{
    struct QlAllocContext * c;
    struct QlId * id1;
    struct QlInt * int1;
    struct QlDouble * dbl1;
    struct QlString * str1;
    struct QlCdr * cdr1;
    struct QlObj * nil = ql_get_nil();
    struct QlObj * t = ql_get_t();

    QL_UT_BEGIN("gctst1");

    c = ql_create_alloc_context();
    QL_UT_VERIFY_CRITICAL((c != NULL) &&
        (nil != NULL) && (ql_type(nil) == QL_OBJ_NIL) &&
        (t != NULL) && (ql_type(t) == QL_OBJ_T));

    id1 = ql_alloc_id(c, "a");
    int1 = ql_alloc_integer(c, 45);
    dbl1 = ql_alloc_double(c, 12.54);
    str1 = ql_alloc_string(c, "test");
    cdr1 = ql_alloc_cdr(c);

    /* test that allocation succeed and we got objects we are expected to get */
    QL_UT_VERIFY_CRITICAL((id1 != NULL) && (int1 != NULL) && (dbl1 != NULL) && (str1 != NULL) && (cdr1 != NULL) &&
        (ql_type(id1) == QL_OBJ_ID) && (ql_type(int1) == QL_OBJ_INT) && (ql_type(dbl1) == QL_OBJ_DOUBLE) &&
        (ql_type(str1) == QL_OBJ_STRING) && (ql_type(cdr1) == QL_OBJ_CDR));
    
    /* value test */
    QL_UT_VERIFY_SILENT(0 == strcmp(ql_get_id_str(id1), "a"));
    QL_UT_VERIFY_SILENT(int1->value == 45);
    QL_UT_VERIFY_SILENT(dbl1->value == 12.54);
    QL_UT_VERIFY_SILENT((cdr1->car == NULL) && (cdr1->cdr == NULL));

    ql_free_alloc_context(c);
    QL_UT_END();
}

/*
 * test pack
 */
void test_ql_obj_allocator()
{
    id_alloc_tst();
    cdr_alloc_tst();
    alloctst1();
}